using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Web.UI.Design;
using System.Windows.Forms;
using Control = System.Web.UI.Control;

namespace WebForms.ControlExtender
{
    public class ControlExtenderDesigner<T> : ControlDesigner where T : TargetControlProperties, new()
    {
        private TargetControlPropertiesCollection<T> _targetProperties;
        private Timer _timer;
        private ControlExtender<T> _validationProvider;

        /// <summary>
        ///   Overrides <see cref = "System.Web.UI.Design.ControlDesigner.GetDesignTimeHtml" />
        /// </summary>
        public override string GetDesignTimeHtml()
        {
            return CreatePlaceHolderDesignTimeHtml();
        }

        public override void Initialize(IComponent component)
        {
            _validationProvider = component as ControlExtender<T>;
            if (_validationProvider == null)
            {
                throw new InvalidOperationException("Unexpected use of ControlExtenderDesigner. " + component);
            }
            base.Initialize(component);
            _targetProperties = _validationProvider.TargetProperties;

            IComponentChangeService service =
                (IComponentChangeService) component.Site.GetService(typeof (IComponentChangeService));
            if (service != null)
            {
                service.ComponentRemoved += OnChangeServiceComponentRemoved;
                service.ComponentRename += OnChangeServiceComponentRename;
            }
        }

        private void OnChangeServiceComponentRemoved(object sender, ComponentEventArgs e)
        {
            if (_validationProvider.CanExtend(e.Component))
            {
                T targetProperties = _targetProperties[((Control) e.Component).ID];

                if (targetProperties != null)
                {
                    _targetProperties.Remove(targetProperties);
                    OnTargetPropertiesChanged();
                }
            }
        }

        private void OnChangeServiceComponentRename(object sender, ComponentRenameEventArgs e)
        {
            if (!_validationProvider.CanExtend(e.Component))
                return;

            T controlItem = _targetProperties[e.OldName];
            if (controlItem != null)
            {
                controlItem.ControlId = e.NewName;

                if (_timer == null)
                {
                    _timer = new Timer();
                    _timer.Tick += OnTimerTick;
                    _timer.Interval = 0x3e8;
                }
                _timer.Enabled = true;
            }
        }

        private void OnTimerTick(object sender, EventArgs e)
        {
            _timer.Enabled = false;
            OnTargetPropertiesChanged();
        }

        protected void OnTargetPropertiesChanged()
        {
            Tag.SetDirty(true);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                IComponentChangeService service =
                    (IComponentChangeService) Component.Site.GetService(typeof (IComponentChangeService));
                if (service != null)
                {
                    service.ComponentRemoved -= OnChangeServiceComponentRemoved;
                    service.ComponentRename -= OnChangeServiceComponentRename;
                }
                if (_timer != null)
                {
                    _timer.Dispose();
                    _timer = null;
                }
            }
            base.Dispose(disposing);
        }
    }
}